const {
  config,
  client,
  singleFileUpload: singleFileUploadAliyun,
  singleFileUploadPrivate,
} = require("../utils/aliyun");
const { singleFileUpload } = require("../utils/aws");
const { BadRequest } = require("http-errors");
var express = require("express");
const { success, failure } = require("../utils/responses");
const path = require("path");
const { STS } = require("ali-oss");
var router = express.Router();
const { Attachment } = require("../models");
const { v4: uuidv4 } = require("uuid");
const moment = require("moment");
const fs = require("fs");

/**
 * 阿里云 OSS 客户端上传
 * POST /uploads/aliyun
 */
router.post("/aliyun", function (req, res) {
  console.log(req.query, "req.query");
  console.log(req.file, "req.file");

  let fn =
    req.query.type === "private" ? singleFileUploadPrivate : singleFileUpload;
  try {
    fn(req, res, async function (error) {
      if (error) {
        return failure(res, error);
      }
      if (!req.file) {
        return failure(res, new BadRequest("请选择要上传的文件。"));
      }
      // 正确处理中文文件名编码
      const originalname = Buffer.from(
        req.file.originalname,
        "latin1"
      ).toString("utf8");
      // 使用 multer-aliyun-oss 已经生成的文件名，确保时间戳一致
      const newFilename = req.file.filename;
      let folder = req.query.folder || "uploads";
      let url =
        req.query.type === "private"
          ? `https://file.cy-zq.cn/${folder}/${newFilename}`
          : `https://images.cy-zq.cn/${folder}/${newFilename}`;

      // 修改上传到OSS的文件名
      req.file.path = folder;
      req.file.url = url;
      //保持到数据库的类型
      if (req.body.imageType) {
        req.file.type = req.body.imageType;
      }
      if (req.body.tag) {
        req.file.tag = req.body.tag;
      }
      if (req.body.filename) {
        req.file.filename = req.body.filename;
      }

      // 记录附件信息
      await Attachment.create({
        ...req.file,
        tag: req.query.tag,
        type: req.query.imageType,
        description: req.query.description,
        imageType: req.query.imageType,
        originalname, // 使用正确编码后的文件名
        userId: req.user.id,
        fullpath: url, // 确保使用正确的 URL
        url, // 显式设置 url 字段，避免被 req.file 中的 url 覆盖
        width: req.query.width,
        height: req.query.height,
      });
      success(res, "上传成功。", { url });
    });
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 获取直传阿里云 OSS 授权信息
 * GET /uploads/aliyun_direct
 */
router.get("/aliyun_direct", async function (req, res, next) {
  // 有效期
  const date = moment().add(1, "days");

  // 自定义上传目录及文件名
  const key = `uploads/${uuidv4()}`;

  // 上传安全策略
  const policy = {
    expiration: date.toISOString(), // 限制有效期
    conditions: [
      ["content-length-range", 0, 100 * 1024 * 1024], // 限制上传文件的大小为：20MB
      { bucket: client.options.bucket }, // 限制上传的 bucket
      ["eq", "$key", key], // 限制上传的文件名
      [
        "in",
        "$content-type",
        ["image/jpeg", "image/png", "image/gif", "image/webp"],
      ], // 限制文件类型
    ],
  };

  // 签名
  const formData = await client.calculatePostSignature(policy);

  // bucket 域名（阿里云上传地址）
  const host = `https://${config.bucket}.${
    (await client.getBucketLocation()).location
  }.aliyuncs.com`.toString();

  // 返回参数
  const params = {
    expire: date.format("YYYY-MM-DD HH:mm:ss"),
    policy: formData.policy,
    signature: formData.Signature,
    accessid: formData.OSSAccessKeyId,
    host,
    key,
    url: host + "/" + key,
  };

  success(res, "获取阿里云 OSS 授权信息成功。", params);
});

// 配置环境变量ALIBABA_CLOUD_ACCESS_KEY_ID。
const accessKeyId = process.env.ALIYUN_ACCESS_KEY_ID;
// const accessKeyId = "LTAI5tLjWCW8bG36WuKDfrDK";
// 配置环境变量ALIBABA_CLOUD_ACCESS_SECRET。
const accessKeySecret = process.env.ALIYUN_ACCESS_KEY_SECRET;
// const accessKeySecret = "XR9tIZwxLghg8M8zSvZuERBQyal9FW";
const ALIYUN_RAM_ROLE_ARN = process.env.ALIYUN_RAM_ROLE_ARN;

/**
 * 提供sts临时凭证, 用于客户端分片直传
 * GET /uploads/aliyun_direct_split
 */
router.get("/get_sts_token_for_oss_upload", (req, res) => {
  let sts = new STS({
    accessKeyId: accessKeyId,
    accessKeySecret: accessKeySecret,
  });
  // roleArn填写步骤2获取的角色ARN，例如acs:ram::175708322470****:role/ramtest。
  // policy填写自定义权限策略，用于进一步限制STS临时访问凭证的权限。如果不指定Policy，则返回的STS临时访问凭证默认拥有指定角色的所有权限。
  // 3000为过期时间，单位为秒。
  // sessionName用于自定义角色会话名称，用来区分不同的令牌，例如填写为sessiontest。
  sts
    .assumeRole(ALIYUN_RAM_ROLE_ARN, ``, "3000", "sessiontest")
    .then((result) => {
      res.json({
        success: true,
        data: {
          accessKeyId: result.credentials.AccessKeyId,
          accessKeySecret: result.credentials.AccessKeySecret,
          stsToken: result.credentials.SecurityToken,
          region: "oss-cn-hangzhou",
          bucket: "chaoyang7521",
        },
      });
    })
    .catch((err) => {
      console.log(err);
      res.status(400).json(err.message);
    });
});

const R2_PUBLIC_URL = "https://pub-8823cf333387408580dd8c1f6a081c5d.r2.dev";

router.post("/r2", singleFileUpload, async (req, res) => {
  try {
    const file = req.file;
    let folder = req.query.folder || "uploads";

    if (!file) {
      return res.status(400).json({ success: false, message: "没有上传文件" });
    }

    // 正确处理中文文件名编码
    const originalname = Buffer.from(file.originalname, "latin1").toString(
      "utf8"
    );

    // 拼接 R2 公网访问地址
    const fileUrl = `${R2_PUBLIC_URL}/${file.key}`;

    // 记录附件信息到数据库（如果需要）
    await Attachment.create({
      ...file,
      originalname,
      filename: file.key, // 这里加上
      path: folder || file.key, // 这里加上
      userId: req.user?.id || 1,
      fullpath: fileUrl,
      url: fileUrl,
      tag: req.query.tag,
      type: req.query.imageType,
      description: req.query.description,
      imageType: req.query.imageType,
      width: req.query.width,
      height: req.query.height,
    });

    res.json({
      success: true,
      data: {
        url: fileUrl,
        filename: file.key,
        originalname: originalname,
        size: file.size,
        mimetype: file.mimetype,
      },
    });
  } catch (error) {
    console.error("上传错误:", error);
    res.status(500).json({ success: false, message: "上传失败" });
  }
});

module.exports = router;
